package com.appspot.secretcuz.endpoint;

import java.util.*;

import javax.annotation.Nullable;
import javax.inject.Named;

import com.appspot.secretcuz.entity.BlogPost;
import com.appspot.secretcuz.entity.BlogPostContent;
import com.google.api.server.spi.config.Api;
import com.google.api.server.spi.response.CollectionResponse;
import com.google.api.server.spi.response.CollectionResponse.Builder;
import com.google.api.server.spi.response.NotFoundException;
import com.google.appengine.api.datastore.Cursor;
import com.google.appengine.api.oauth.OAuthRequestException;
import com.google.appengine.api.users.User;
import com.googlecode.objectify.cmd.Query;

import static com.appspot.secretcuz.entity.OfyService.ofy;

@Api(
	name = "bapi",
	description = "SecretCuz Blog API",
	version = "v1",
	clientIds = {Ids.WEB_CLIENT_ID, Ids.ANDROID_CLIENT_ID, Ids.IOS_CLIENT_ID},
    audiences = {Ids.ANDROID_AUDIENCE}
)
public class BlogPostEndpoint {
	public CollectionResponse<BlogPost> listBlogPost(@Nullable @Named("cursor") String cursorString, @Nullable @Named("limit") Integer limit) {
		if (limit == null) {
			limit = 10;
		}
		Query<BlogPost> query;
		if (limit == 0) {
			query = ofy().load().type(BlogPost.class).order("-date");
		} else if (cursorString == null || cursorString == "") {
			query = ofy().load().type(BlogPost.class).order("-date").limit(limit);
		} else {
			query = ofy().load().type(BlogPost.class).order("-date").limit(limit).startAt(Cursor.fromWebSafeString(cursorString));
		}
		List<BlogPost> retList = query.list();
		String retCursor = query.iterator().getCursor().toWebSafeString();
		return new Builder<BlogPost>().setItems(retList).setNextPageToken(retCursor).build();
	}

	public BlogPost getBlogPost(@Named("id") Long id) throws NotFoundException {
		BlogPost bp = ofy().load().type(BlogPost.class).id(id).get();
		if (bp == null) {
			throw new NotFoundException("No entity with the id " + id + " exists.");
		}
		BlogPostContent bpc = ofy().load().type(BlogPostContent.class).id(id).get();
		if (bpc == null) {
			throw new NotFoundException("No entity with the id " + id + " exists.");
		}
		bp.setContent(bpc.getContent());
		return bp;
	}

	public BlogPost insertBlogPost(BlogPost bp) {
		BlogPostContent bpc = new BlogPostContent();
		bpc.setContent(bp.getContent());
		//save BlogPost without content
		bp.setContent("");
		ofy().save().entity(bp).now();
		bpc.setId(bp.getId());
		ofy().save().entity(bpc).now();
		return bp;
	}

	public BlogPost updateBlogPost(@Named("id") Long id, BlogPost bp) throws NotFoundException {
		BlogPost updatedBp = ofy().load().type(BlogPost.class).id(id).get();
		if (updatedBp == null) {
			throw new NotFoundException("No entity with the id " + id + " exists.");
		}
		BlogPostContent updatedBpc = ofy().load().type(BlogPostContent.class).id(id).get();
		if (updatedBpc == null) {
			throw new NotFoundException("No entity with the id " + id + " exists.");
		}
		if (bp.getTitle() != null) {
			updatedBp.setTitle(bp.getTitle());
		}
		if (bp.getMeta() != null) {
			updatedBp.setMeta(bp.getMeta());
		}
		if (bp.getDate() != null) {
			updatedBp.setDate(bp.getDate());
		}
		if (bp.getAuthor() != null) {
			updatedBp.setAuthor(bp.getAuthor());
		}
		if (bp.getContent() != null) {
			updatedBpc.setContent(bp.getContent());
		}
		ofy().save().entity(updatedBp).now();
		ofy().save().entity(updatedBpc).now();
		//return BlogPost with content
		bp.setContent(updatedBpc.getContent());
		return bp;
	}

	public void removeBlogPost(@Named("id") Long id, User user) throws OAuthRequestException, NotFoundException {
		if (user != null) {
			BlogPost deletedBp = ofy().load().type(BlogPost.class).id(id).get();
			if (deletedBp == null) {
				throw new NotFoundException("No entity with the id " + id + " exists.");
			}
			BlogPostContent deletedBpc = ofy().load().type(BlogPostContent.class).id(id).get();
			if (deletedBpc == null) {
				throw new NotFoundException("No entity with the id " + id + " exists.");
			}
			ofy().delete().entity(deletedBp);
			ofy().delete().entity(deletedBpc);
		} else {
			throw new OAuthRequestException("Invalid user.");
		}
	}
}
